package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	"sync"
	"time"
	//"github.com/tencentyun/scf-go-lib/cloudfunction"
)

type DefineEvent struct {
	// test event define
	IsBase64Encoded bool `json:"isBase64Encoded"`
	StatusCode      int  `json:"statusCode"`
	Headers         interface{}
	Body            string
}
type mlock struct {
	sync.Mutex
}

var e = DefineEvent{
	IsBase64Encoded: false,
	StatusCode:      200,
	Headers:         h,
}
var h = struct {
	ContextType string `json:"Content-Type"`
}{
	ContextType: "text/html",
}
var b = struct {
	Luxingniao  string `json:"luxingniao"`
	Moguli      string `json:"moguli"`
	Maoxiaopang string `json:"maoxiaopang"`
	Haimaochawu string `json:"haimaochawu"`
	Mengyachi   string `json:"mengyachi"`
	C           int
	U           int
}{
	Luxingniao:  "false",
	Moguli:      "false",
	Maoxiaopang: "false",
}
var clock mlock
var luxingniaolock mlock
var maoxiaopanglock mlock
var mogulilock mlock
var tlock mlock
var maoxiaopang_status string
var luxingniao_status string
var moguli_status string
var count int
var sleeptime = 3

const max_time = 1200
const maoxiaopang_ip = "ffxivlobby07.ff14.sdo.com"
const luxingniao_ip = "ffxivlobby01.ff14.sdo.com"
const moguli_ip = "ffxivlobby05.ff14.sdo.com"

const haimaochawu = "116.211.8.45"
const haimao_port = "54993"

const mengyachi = "109.244.5.44"
const mengyachi_port = "55026"

var haimao_status = "false"
var haimaolock mlock
var mengya_status = "false"
var mengyalock mlock

func getServerStatus() {
	clock.Lock()
	count++
	if count > 30000 {
		count = 1
	}
	clock.Unlock()
	go func() {
		conn, err := net.DialTimeout("tcp", net.JoinHostPort(luxingniao_ip, "54994"), time.Second)
		if err != nil {
			luxingniaolock.Lock()
			luxingniao_status = "false"
			luxingniaolock.Unlock()
			log.Println("luxingniao gate failed")
		}
		if conn != nil {
			_ = conn.Close()
			luxingniaolock.Lock()
			luxingniao_status = "true"
			luxingniaolock.Unlock()
		}
	}()

	go func() {
		conn, err := net.DialTimeout("tcp", net.JoinHostPort(mengyachi, mengyachi_port), time.Second)
		if err != nil {
			mengyalock.Lock()
			mengya_status = "false"
			mengyalock.Unlock()
			log.Println("mengyachi server failed")
		}
		if conn != nil {
			_ = conn.Close()
			mengyalock.Lock()
			mengya_status = "true"
			mengyalock.Unlock()
		}
	}()
	go func() {
		conn, err := net.DialTimeout("tcp", net.JoinHostPort(haimaochawu, haimao_port), time.Second)
		if err != nil {
			haimaolock.Lock()
			haimao_status = "false"
			haimaolock.Unlock()
			log.Println("haimaochawu server failed")
		}
		if conn != nil {
			_ = conn.Close()
			haimaolock.Lock()
			haimao_status = "true"
			haimaolock.Unlock()
		}
	}()
	go func() {
		conn, err := net.DialTimeout("tcp", net.JoinHostPort(moguli_ip, "54994"), time.Second)
		if err != nil {
			mogulilock.Lock()
			moguli_status = "false"
			mogulilock.Unlock()
			log.Println("moguli_ip gate failed")
		} else {

			if conn != nil {
				_ = conn.Close()
				mogulilock.Lock()
				moguli_status = "true"
				mogulilock.Unlock()

			}
		}
	}()
	go func() {
		conn, err := net.DialTimeout("tcp", net.JoinHostPort(maoxiaopang_ip, "54994"), time.Second)
		if err != nil {
			maoxiaopanglock.Lock()
			maoxiaopang_status = "false"
			maoxiaopanglock.Unlock()
			log.Println("maoxiaopang_ip gate failed")
		} else {
			if conn != nil {
				_ = conn.Close()
				maoxiaopanglock.Lock()
				maoxiaopang_status = "true"
				maoxiaopanglock.Unlock()

			}
		}

	}()

}
func ping(ctx context.Context, event DefineEvent) (DefineEvent, error) {

	tlock.Lock()
	sleeptime = 0
	tlock.Unlock()

	b.Maoxiaopang = maoxiaopang_status
	b.Luxingniao = luxingniao_status
	b.Moguli = moguli_status
	b.Haimaochawu = haimao_status
	b.C = count
	t, _ := json.Marshal(b)

	e.Body = string(t)

	return e, nil
}
func setupResponse(w *http.ResponseWriter, req *http.Request) {
	(*w).Header().Set("Access-Control-Allow-Origin", "http://xaviermoon.gitee.io")
	(*w).Header().Set("Content-Type", "application/json")
	(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-ID")
}

type Uids struct {
	M map[string]int
	sync.RWMutex
}

var uStatic Uids

func clearUser() {
	//清理用户
	for {
		now := time.Now().Second()
		m := &(uStatic.M)
		uStatic.Lock()
		for u, t := range *m {
			if (now - t) > 30*1 {
				delete(uStatic.M, u)
			}
		}
		uStatic.Unlock()
		time.Sleep(time.Minute * 5)
	}

}
func countUser() int {
	i := 0
	uStatic.RLock()
	defer uStatic.RUnlock()
	for range uStatic.M {
		i++
	}
	return i
}
func updateUser(u string) {
	uStatic.Lock()
	defer uStatic.Unlock()
	now := time.Now().Second()
	uStatic.M[u] = now
}
func main() {
	uStatic = Uids{M: map[string]int{}}
	go func() {
		for ; ; {

			if sleeptime < 3 {
				getServerStatus()
				tlock.Lock()
				sleeptime++
				tlock.Unlock()
			}
			time.Sleep(1 * time.Second)
		}

	}()
	go clearUser()

	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		setupResponse(&w, r)

		if (*r).Method == "OPTIONS" {
			return
		}
		uid := r.Header.Get("X-ID")
		if uid != "" {
			go updateUser(uid)
		}

		tlock.Lock()
		sleeptime = 0
		tlock.Unlock()
		b.U = countUser()
		b.Mengyachi = mengya_status
		b.Maoxiaopang = maoxiaopang_status
		b.Luxingniao = luxingniao_status
		b.Moguli = moguli_status
		b.Haimaochawu = haimao_status
		b.C = count
		t, _ := json.Marshal(b)

		fmt.Fprint(w, string(t))

	})

	http.ListenAndServe(":31167", nil)

	//cloudfunction.Start(ping)
}
